package com.szxy.hyboot.uitls.http;


import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by ZHW on 2017/12/7.
 */
public class HttpsUtils {

    private static final Logger logger = LoggerFactory.getLogger(HttpsUtils.class);


    /**
     * 从https服务器接收字符串数据(以字节流方式接收)GET
     *
     * @param pURL 服务器地址及调用参数,例如:https://vitality/server/ConfigAdmin?type=get&param=ZoneMap
     * @return 接收的字符串
     * @throws IOException
     * @throws Throwable
     */
    public static String receiveHttpsDataByBytes(String pURL, HashMap<String, String> headerParam,
                                                 HashMap<String, String> requestUrlParam, String pMethod, String pEncode) throws IOException {
        HttpsURLConnection.setDefaultHostnameVerifier(new NullHostNameVerifier());

        StringBuffer buffer = null;
        try {
            // 创建SSLContext
            SSLContext sslContext = SSLContext.getInstance("SSL");
            TrustManager[] tm =
                    {new MyX509TrustManager()};
            // 初始化
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 获取SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            URL url = new URL(pURL);
            if (pMethod.equals("GET") || pMethod == "GET") {
                if (null != requestUrlParam && false == requestUrlParam.isEmpty()) {
                    StringBuilder sb = new StringBuilder();
                    Iterator<Map.Entry<String, String>> iterator = requestUrlParam.entrySet()
                            .iterator();
                    while (iterator.hasNext()) {
                        if (sb.length() > 0) {
                            sb.append('&');
                        }
                        Map.Entry<String, String> entry = iterator.next();
                        String key = entry.getKey();
                        String value;
                        try {
                            value = URLEncoder.encode(entry.getValue(),
                                    "utf-8");
                        } catch (UnsupportedEncodingException e) {
                            logger.error("[URLEncoder.encode({},{});]", entry.getValue());
                            //LogUtils.d("error={}", e);
                            value = "";
                        }
                        sb.append(key).append('=').append(value);
                    }
                    url = new URL(pURL + "?" + sb.toString());
                }
            }
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            // 设置当前实例使用的SSLSoctetFactory
            conn.setSSLSocketFactory(ssf);
            conn.setHostnameVerifier(new NullHostNameVerifier());
            conn.connect();
            if (pMethod.equals("POST") || pMethod == "POST") {
                // 往服务器端写内容
                OutputStream out = conn.getOutputStream();
                /* set up request */
                if (null != requestUrlParam && false == requestUrlParam.isEmpty()) {
                    StringBuffer sb = new StringBuffer();
                    Set<String> mapNames = requestUrlParam.keySet();
                    for (String mapName : mapNames) {
                        sb.append("&");
                        sb.append(URLEncoder.encode(mapName, pEncode));
                        sb.append("=");
                        sb.append(URLEncoder.encode(requestUrlParam.get(mapName), pEncode));
                    }
                    String request = sb.substring(1);
                    out.write(request.getBytes());
                }
                out.flush();
            }
//            if(pMethod.equals("POST")|| pMethod=="POST") {
//                //URL url = new URL(pURL);
//                conn = (HttpsURLConnection) url.openConnection();
//                conn.setDoOutput(true);
//                conn.setDoInput(true);
//                conn.setUseCaches(false);
//                conn.setRequestMethod(pMethod);
//                // 设置当前实例使用的SSLSoctetFactory
//                conn.setSSLSocketFactory(ssf);
//                conn.setHostnameVerifier(new NullHostNameVerifier());
//                conn.connect();
//                // 往服务器端写内容
//                OutputStream out = conn.getOutputStream();
//
//			/* set up request */
//                if (null != requestUrlParam && false == requestUrlParam.isEmpty()) {
//                    StringBuffer sb = new StringBuffer();
//                    Set<String> mapNames = requestUrlParam.keySet();
//                    for (String mapName : mapNames) {
//                        sb.append("&");
//                        sb.append(URLEncoder.encode(mapName, pEncode));
//                        sb.append("=");
//                        sb.append(URLEncoder.encode(requestUrlParam.get(mapName), pEncode));
//                    }
//                    String request = sb.substring(1);
//                    out.write(request.getBytes());
//                }
//                out.flush();
//            }
//            else
//            {
//                //URL url =null;
//                if (null != requestUrlParam && false == requestUrlParam.isEmpty()) {
//                    List<NameValuePair> params = new ArrayList<NameValuePair>();
//                    Iterator iter = requestUrlParam.entrySet().iterator();
//                    while (iter.hasNext()) {
//                        Map.Entry entry = (Map.Entry) iter.next();
//                        String name = (String) entry.getKey();
//                        String value = (String) entry.getValue();
//                        params.add(new BasicNameValuePair(name, value));
//                    }
//                    // 设置参数
//                    String str = EntityUtils.toString(new UrlEncodedFormEntity(params));
//                    url = new URL(pURL+"?"+str);
//                }
//                else
//                {
//                    url = new URL(pURL);
//                }
//                conn = (HttpsURLConnection) url.openConnection();
//                conn.setDoOutput(true);
//                conn.setDoInput(true);
//                conn.setUseCaches(false);
//                conn.setRequestMethod(pMethod);
//                // 设置当前实例使用的SSLSoctetFactory
//                conn.setSSLSocketFactory(ssf);
//                conn.setHostnameVerifier(new NullHostNameVerifier());
//                conn.connect();
//            }
            InputStream is = conn.getInputStream();
            InputStreamReader isr = new InputStreamReader(is, "utf-8");
            BufferedReader br = new BufferedReader(isr);
            buffer = new StringBuffer();
            String line = null;
            while ((line = br.readLine()) != null) {
                buffer.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null == buffer ? null : buffer.toString();
    }


    /**
     * 从https服务器接收字符串数据(以字节流方式接收)GET
     *
     * @param pURL 服务器地址及调用参数,例如:https://vitality/server/ConfigAdmin?type=get&param=ZoneMap
     * @return 接收的字符串
     * @throws IOException
     * @throws Throwable
     */
    public static String receiveHttpsDataByBytes(String pURL, HashMap<String, String> requestUrlParam,
                                                 String pMethod, String pEncode) {
        List<NameValuePair> nameValuePairList = new ArrayList<>();
        try {
            requestUrlParam.keySet().forEach(mapName -> {
                String key = null;
                String value = null;
                try {
                    key = URLEncoder.encode(mapName, pEncode);
                    value = URLEncoder.encode(requestUrlParam.get(mapName), pEncode);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                if (key != null) {
                    NameValuePair nameValuePair = new BasicNameValuePair(key, value);
                    nameValuePairList.add(nameValuePair);
                }
            });
            if (HttpClientService.HTTP_METHOD_GET.equals(pMethod)) {
                // 发送  https get
                return HttpClientService.sendHttpsGet(pURL, nameValuePairList);
            }
            // 发送 https post
            return HttpClientService.sendHttpsPost(pURL, nameValuePairList);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 发送https协议数据
     *
     * @param restUrl
     * @param param
     * @return
     */
    public static String doPost(String restUrl, String param, String contentType) {

        StringBuffer sb = new StringBuffer();
        HttpsURLConnection httpsConn = null;
        PrintWriter out = null;
        try {
            URL url = new URL(restUrl);
            TrustManager tm[] = new TrustManager[1];
            tm[0] = new MyX509TrustManager();
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());

            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            // 创建HttpsURLConnection对象，并设置其SSLSocketFactory对象
            httpsConn = (HttpsURLConnection) url.openConnection();
            httpsConn.setSSLSocketFactory(ssf);

            httpsConn.setDoOutput(true); // 获取返回数据需要设置为true 默认false
            httpsConn.setDoInput(true); // 发送数据需要设置为true 默认false
            httpsConn.setReadTimeout(5000);
            if (contentType != null)
                httpsConn.setRequestProperty("Content-type", contentType);

            httpsConn.setConnectTimeout(5000);
            httpsConn.setRequestMethod("POST");
            out = new PrintWriter(httpsConn.getOutputStream());

            out.print(param);

            out.flush();

            out.close();
            BufferedReader red = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(), "utf-8"));

            String line;
            while ((line = red.readLine()) != null) {
                sb.append(line);
            }
            red.close();
        } catch (Exception e) {
            logger.error("发送数据=" + param + "REQUEST_RESPONSE_ERROR, URL = " + restUrl, e);
        } finally {

            try {
                if (out != null) {
                    out.close();
                }
                if (httpsConn != null) {
                    httpsConn.disconnect();
                }
            } catch (Exception e) {
                logger.error("关闭资源出错, URL = " + restUrl, e);
            }
        }
        return sb.toString();
    }

    /**
     * <p>https是对链接加了安全证书SSL的，如果服务器中没有相关链接的SSL证书，它就不能够信任那个链接，也就不会访问到了。
     * <p>所以我们第一步是自定义一个信任管理器。自要实现自带的X509TrustManager接口就可以了
     *
     * @author NeilCao (poss@poss.cn)
     * @Description:
     * @Company: POSS软件平台 (www.poss.cn)
     * @Copyright: Copyright (c) 2003-2017
     * @version: POSS_3.0
     * @date: 2017年12月4日
     */
    public static class MyX509TrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

    }

    public static class NullHostNameVerifier implements HostnameVerifier {
        /* (non-Javadoc)
         *
         * @see javax.net.ssl.HostnameVerifier#verify(java.lang.String,
         * javax.net.ssl.SSLSession)
         * */
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }
    }

}
